package com.rp.system.user.controller;


import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rp.common.aspect.annotetion.AutoLog;
import com.rp.common.aspect.annotetion.DictGo;
import com.rp.common.aspect.annotetion.ResponseResultBody;
import com.rp.common.config.shiro.ShiroRealm;
import com.rp.common.config.shiro.ShiroSessionListener;
import com.rp.common.result.ResultDTO;
import com.rp.common.utils.*;
import com.rp.system.log.entity.SysLog;
import com.rp.system.log.service.SysLogService;
import com.rp.system.user.entity.SysPermission;
import com.rp.system.user.entity.SysUser;
import com.rp.system.user.model.GroupInsert;
import com.rp.system.user.model.SysRolePermissionModel;
import com.rp.system.user.model.SysUserModel;
import com.rp.system.user.model.UpdatePassWordModel;
import com.rp.system.user.service.SysPermissionService;
import com.rp.system.user.service.SysRolePermissionService;
import com.rp.system.user.service.SysUserService;
import com.rp.system.user.service.impl.SysPermissionServiceImpl;
import com.rp.system.user.service.impl.SysUserServiceImpl;
import com.rp.common.config.redis.RedisUtil;
import com.rp.system.user.util.JuheUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author vicente
 * @since 2020-11-23
 */
@Slf4j
@RestController
@RequestMapping("/sys-user")
@ResponseResultBody
@Api(tags = "用户管理")
public class SysUserController {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private Selectway selectway;

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private RedisUtil redisUtil;

    //登录图形验证码key
    public static final String KEY_CAPTCHA = "KEY_CAPTCHA";


    /**
     * @Author HuJingYu
     * @Date 15:42 2020-12-11
     * @Description 测试阶段默认验证码0000 正式上线时去掉
     */
    private static final String CAPTCHA = "0000";

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ApiOperation(value = "用户登录")
    public ResultDTO loginUser(@RequestBody @Validated SysUserModel sysUserModel, HttpServletRequest request) {
        System.out.println(sysUserModel);
        //校验验证码
        //session中的验证码
        String sessionCaptcha = (String) SecurityUtils.getSubject().getSession().getAttribute(KEY_CAPTCHA);
        //测试阶段默认验证码0000
        if (null != sysUserModel.getCaptcha() && !CAPTCHA.equals(sysUserModel.getCaptcha())) {
            if (null == sysUserModel.getCaptcha() || !sysUserModel.getCaptcha().equalsIgnoreCase(sessionCaptcha)) {
                return ResultDTO.bad().message("验证码错误");
            }
        }
        //去掉空格
        sysUserModel.setUsername(sysUserModel.getUsername().trim());
        sysUserModel.setPassword(sysUserModel.getPassword().trim());
        //如果有点击  记住我
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(sysUserModel.getUsername(), sysUserModel.getPassword(), sysUserModel.getRememberMe());
        Subject subject = SecurityUtils.getSubject();
        try {
            //登录操作
            subject.login(usernamePasswordToken);
            //保存日志
            String username = (String) SecurityUtils.getSubject().getPrincipal();
            SysUser user = sysUserService.showUser(username);
            System.out.println(SecurityUtils.getSubject().getSession().getId());
            user.setToken((String)SecurityUtils.getSubject().getSession().getId());
            sysLogService.save(new SysLog(1, "用户: " + sysUserModel.getUsername() + ",登录成功！", sysUserModel.getUsername(), user.getRealname(), request));
            return ResultDTO.success().data(user).message("登录成功");
        } catch (UnknownAccountException uae) {
            return ResultDTO.USER_NOT_EXIST();
        } catch (LockedAccountException lae) {
            return ResultDTO.USER_ACCOUNT_FORBIDDEN();
        } catch (AuthenticationException ice) {
            return ResultDTO.USER_LOGIN_ERROR();
        }
    }

    @AutoLog(value = "用户管理-修改密码")
    @ApiOperation(value = "修改密码")
    @PostMapping("/updatePassWord")
    public ResultDTO<Boolean> updatePassWord(@RequestBody UpdatePassWordModel updatePassWordModel) {
        redisUtil.delAll(SysUserServiceImpl.KEY_STRING);
        return ResultDTO.tf(sysUserService.updatePassWord(updatePassWordModel));
    }

    @ApiOperation(value = "安全退出")
    @GetMapping("/logout")
    public ResultDTO logout(HttpServletRequest request) {
        //走自己封装的logout
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        ShiroRealm shiroRealm = (ShiroRealm) securityManager.getRealms().iterator().next();
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        if (principals != null) {
            String username = (String) SecurityUtils.getSubject().getPrincipal();
            SysUser user = sysUserService.findSysUserByUsername(username);
            sysLogService.save(new SysLog(1, "用户: " + username + ",退出登录！", username, user.getRealname(), request));
            shiroRealm.clearCache(principals);
        }
        SecurityUtils.getSubject().logout();
        return ResultDTO.success().message("退出登录成功");
    }

    @DictGo
//    @AutoLog(value = "用户管理-查看当前登录用户")
    @ApiOperation(value = "查看当前登录用户")
    @RequestMapping(value = "/showUser", method = RequestMethod.GET)
    public ResultDTO showUser() {
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        return ResultDTO.success().data(sysUserService.showUser(username));
    }

    @AutoLog(value = "用户管理-在线总人数")
    @ApiOperation(value = "在线总人数")
    @GetMapping("/people")
    public ResultDTO people() {
        ShiroSessionListener shiroSessionListener = new ShiroSessionListener();
        return ResultDTO.success().data(shiroSessionListener.getSessionCount());
    }

    @AutoLog(value = "用户管理-获取验证码图片")
    @ApiOperation(value = "获取验证码图片")
    @GetMapping("/Captcha.jpg")
    public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置相应类型,告诉浏览器输出的内容为图片
        response.setContentType("image/jpeg");
        // 不缓存此内容
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        try {
            HttpSession session = request.getSession();
            CaptchaUtil tool = new CaptchaUtil();
            StringBuffer code = new StringBuffer();
            BufferedImage image = tool.genRandomCodeImage(code);
            session.removeAttribute(KEY_CAPTCHA);
            session.setAttribute(KEY_CAPTCHA, code.toString());
            // 将内存中的图片通过流动形式输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @DictGo
    @AutoLog(value = "用户管理-分页列表")
    @RequiresPermissions("sysUser:list")
    @ApiOperation(value = "分页列表")
    @GetMapping("/list")
    public ResultDTO<SysUser> list(
            @RequestParam(defaultValue = "1", required = false) @ApiParam(value = "当前页面") int pageNum,
            @RequestParam(defaultValue = "20", required = false) @ApiParam(value = "每页显示的数量") int pageSize,
            @RequestParam(required = false) @ApiParam(value = "模糊查询字符串") String string) {
        Api anno = SysUserController.class.getAnnotation(Api.class);

        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        selectway.fields(queryWrapper, string,"sys_user","u",null);
        queryWrapper.eq("u.del_flag", 0);
        queryWrapper.orderByDesc("u.create_time");
        return ResultDTO.success().data(sysUserService.selectMyPage(new Page<>(pageNum, pageSize), queryWrapper));
    }

    @AutoLog(value = "用户管理-增加")
    @ApiOperation(value = "增加")
    @RequiresPermissions("sysUser:update")
    @PostMapping("/insert")
    public ResultDTO<IPage<SysUser>> insert(@RequestBody  SysUser sysUser) {
        redisUtil.delAll(SysUserServiceImpl.KEY_STRING);
        redisUtil.delAll(SysPermissionServiceImpl.KEY_STRING);
        return ResultDTO.tf(sysUserService.save(sysUser));
    }

    @AutoLog(value = "用户管理-注册")
    @ApiOperation(value = "注册")
    @PostMapping("/register")
    public ResultDTO register(@RequestBody  SysUser sysUser) {
        SysUser old = sysUserService.getOne(new QueryWrapper<SysUser>().eq("username", sysUser.getUsername()));
        if(!NullIs.isEmpty(old)){
            return ResultDTO.bad().message("用户名已被注册");
        }
        SysUser old2 = sysUserService.getOne(new QueryWrapper<SysUser>().eq("tel", sysUser.getPhone()));
        if(!NullIs.isEmpty(old2)){
            return ResultDTO.bad().message("手机号已被注册");
        }
        if(redisUtil.hasKey(sysUser.getPhone())){
            if(sysUser.getCode().equals(redisUtil.get(sysUser.getPhone()))){
                redisUtil.del(sysUser.getPhone());
                boolean boo = sysUserService.save(sysUser);
                return ResultDTO.tf(boo);
            }
            return ResultDTO.bad().message("验证码错误");
        }else{
            return ResultDTO.bad().message("验证码失效");
        }

    }

    @AutoLog(value = "用户管理-修改")
    @ApiOperation(value = "修改")
    @RequiresPermissions("sysUser:update")
    @PutMapping("/update")
    public ResultDTO<IPage<SysUser>> update(@RequestBody SysUser sysUser) {
        redisUtil.delAll(SysUserServiceImpl.KEY_STRING);
        redisUtil.delAll(SysPermissionServiceImpl.KEY_STRING);
        return ResultDTO.tf(sysUserService.updateById(sysUser));
    }

    @AutoLog(value = "用户管理-删除")
    @ApiOperation(value = "删除")
    @RequiresPermissions("sysUser:update")
    @DeleteMapping("/delete")
    public ResultDTO delete(@RequestBody @ApiParam(value = "id", required = true) String id) {
        redisUtil.delAll(SysUserServiceImpl.KEY_STRING);
        return ResultDTO.tf(sysUserService.removeById(id));
    }

    @AutoLog(value = "用户管理-批量删除")
    @ApiOperation(value = "批量删除")
    @RequiresPermissions("sysUser:update")
    @DeleteMapping("/deleteAll")
    public ResultDTO deleteAll(@RequestBody @ApiParam(value = "id(英文逗号隔开)", required = true) String ids) {
        redisUtil.delAll(SysUserServiceImpl.KEY_STRING);
        return ResultDTO.tf(sysUserService.removeByIds(Arrays.asList(ids.split(","))));
    }

    @ApiOperation(value = "测试增加用户")
    @PostMapping("/lt/insert")
    public ResultDTO<IPage<SysUser>> ltinsert(@RequestBody @Validated({GroupInsert.class}) SysUser sysUser) {

        return ResultDTO.tf(sysUserService.save(sysUser));
    }

    @Autowired
    private SysPermissionService sysPermissionService;
    @Autowired
    private SysRolePermissionService sysRolePermissionService;

    @ApiOperation(value = "测试赋值全部权限")
    @PostMapping("/lt/perssioninsert")
    public ResultDTO<IPage<SysUser>> ltperssioninsert(@RequestParam @ApiParam(value = "角色ID", required = true) String ids) {
        SysRolePermissionModel sysRolePermissionModel = new SysRolePermissionModel();
        List<String> list =  new ArrayList<>();
        for(SysPermission sysPermission : sysPermissionService.list()){
            list.add(sysPermission.getId());
        }
        sysRolePermissionModel.setPermissionIds(list);
        sysRolePermissionModel.setRoleId(ids);
        sysRolePermissionService.insertOrDelete(sysRolePermissionModel);

        return ResultDTO.success();
    }
    @ApiOperation(value = "获取验证码")
    @GetMapping("/getAuthCode")
    public ResultDTO getAuthCode(@RequestParam @ApiParam(value = "手机号",required = true) String tel) {
        if(JuheUtil.isMobileNumber(tel)){
            if(redisUtil.hasKey(tel)){
                long time = redisUtil.getExpire(tel);
                if(300 - time < 60){
                    return ResultDTO.bad().message("请勿重复发送," + (300 - time) + "秒后重试");
                }
            }
            String code = RandomUtil.randomNumbers(6);
            redisUtil.set(tel,code,300);
            JuheUtil.mobileQuery(tel,code);
            return ResultDTO.success();
        }
        return ResultDTO.bad().message("手机号格式错误");
    }

}
